#!/bin/env python
#-*- coding:utf-8 -*-

#----------------------------------------------------------------------------
# Name     :      GUI.py
# Purpose  :      Mysql tool for ucweb, and this is the py file of gui.
# Author   :      Albert cheng
# Created  :      2012-10-29
# Copyright:     (c) 2012 by Albertcheng
# Licence  :      wxWindows license
#----------------------------------------------------------------------------
import os
import re
import time
import string
import wx          
import sys
import wx.lib.delayedresult as dr
wx.SetDefaultPyEncoding("utf-8")


from gui_dbconfig import DBConfigDialog
from gui_DataGrid import DataConfigDialog
from gui_grid import GRID_STRING,GRID_NUMBER,GRID_BOOL,GRID_CHOICE,CustTableGrid
from log import Log
from dbo import *
from request_handler import request_mysql,request_sqlite,request_xml
    
class GUITool(wx.Frame):
    def __init__(self, parent, title):
        #=======================================================================
        # 初始化部分参数和变量
        #=======================================================================
        
        self.Log = Log()
        self.Log.log("program started. initialized variables.")
        self.errflag = False
        self.Title_Msg = title
        self.refresh_mysql_flag = False
        
        self.sqlite_request = request_sqlite(self.Log)
        self.cfg = self.sqlite_request.get()
        self.db_cfg = self.cfg[0]
        self.prefer_cfg = self.cfg[1][0]
        print self.prefer_cfg
        self.mysql_request = request_mysql(self.Log,self.db_cfg)
        self.xml_request = request_xml(self.Log)
        self.xml_cfg = self.xml_request.read_cfg()
        self.projs = list(set(self.xml_cfg.keys()))
        self.proj_id = self.prefer_cfg[1]
        self.proj = self.projs[self.proj_id]
        
        self.player = {}
        self.refresh_proj(self.proj)
        
        self.Log.log("tool started. initialized tool gui.")
        #=======================================================================
        # 界面的主画布初始化
        #=======================================================================
        wx.Frame.__init__(self, parent, -1, title, size = (900, 720),
                          style= wx.CAPTION| wx.MINIMIZE_BOX |wx.CLOSE_BOX| wx.NO_FULL_REPAINT_ON_RESIZE)
        self.SetMinSize((300,300))
        
        #=======================================================================
        # 界面状态栏初始化和设置
        #=======================================================================
        self.CreateStatusBar()
        self.SetStatusText(self.Title_Msg)
        #=======================================================================
        # 界面菜单栏处理
        #=======================================================================
        self.menu_prepare()
        #=======================================================================
        # 界面布局处理
        #=======================================================================
        self.main_sizer_prepare()

        #=======================================================================
        # 界面和数据库的连接检查 
        #=======================================================================
        self.Log.log("gui render finished, about to try to connect to mysql server.")
        self.run_bg_mysql_thread()
               
        #=======================================================================
        # 所有操作事件的绑定
        #=======================================================================
        self.__evt_binding()
        
    def refresh_proj(self,proj):

        
        self.player_detail_ui_label = [
                                    ["UC账号".decode('utf-8'),"PlayerID","角色名".decode('utf-8'),"等级".decode('utf-8'),"经验值".decode('utf-8')],
                                    ["最近登陆时间".decode('utf-8'), "活力值".decode('utf-8'),"敏捷属性".decode('utf-8'),"力量属性".decode('utf-8')],
                                    ]
        if proj == "ssdz":
            
            self.prop_file = r"./xml/ssdz/props.xml"
            self.skill_file = r"./xml/ssdz/skills.xml"
            self.equip_file = r"./xml/ssdz/gears.xml"
            #--------------------------
            self.player_detail_ui_label[1].append("速度属性".decode('utf-8'))
            
            self.player_detail_ui_label.append(["Vip到期时间".decode('utf-8'),"Vip等级".decode('utf-8'),"Vip经验".decode('utf-8')])
                                    
            self.player_detail_ui_label.append(["敏捷丸（小）".decode('utf-8'),"力量丸（小）".decode('utf-8'),"速度丸（小）".decode('utf-8'),"经验丸（小）".decode('utf-8')])
            self.player_detail_ui_label.append(["超级敏捷丸".decode('utf-8'),"超级力量丸".decode('utf-8'),"超级速度丸".decode('utf-8'),"超级经验丸".decode('utf-8')])
            self.player_detail_ui_label.append(["button|编辑".decode('utf-8'),"button|保存".decode('utf-8')])


                                    
            self.player_detail_ui_value_tag = [
                                    "t_player.uc_id","t_player.id","t_player.name","t_player.level","t_player.exp",
                                    "t_player.last_login_time","t_player.energy,t_player.max_energy","t_player.agility","t_player.power",
                                    "t_player.speed",
                                    "t_player.vip_deadline","t_player_misc.vip_exp","t_player_misc.vip_level",#"t_player.max_hp","t_player_prop.count.prop_id.8",
                                    "t_player_state.agility","t_player_state.power","t_player_state.speed","t_player_state.attack",
                                    "t_player_state.super_agility","t_player_state.super_power","t_player_state.super_speed","t_player_state.super_attack",
                                    "self.Evt_OnEditRoleSizer","self.Evt_OnSaveRoleSizer",
                                    ]
        
            #--------------------------
            
        elif proj == "douhun":
            
            self.prop_file = r"./xml/douhun/prop.xml"
            self.skill_file = r"./xml/douhun/attackskills.xml"
            self.equip_file = r"./xml/douhun/equipment.xml"
            #--------------------------
            self.player_detail_ui_label[1].append("智力属性".decode('utf-8'))
            
            self.player_detail_ui_label.append(["功勋值".decode('utf-8'),"元宝".decode('utf-8'),"职业".decode('utf-8')])
            self.player_detail_ui_value_tag = [
                                    "k_player.ucId","k_player.id","k_player.name","k_player.level","k_player.exp",
                                    "k_player.lastLoginTime","k_player.energy,k_player.maxEnergy","k_player_fightmsg.agility","k_player_fightmsg.strength","k_player_fightmsg.intellect",
                                    "k_player.exploit","k_player.money","k_player_fightmsg.role",
                                    "k_player_prop_effect.LAttackCount","k_player_prop_effect.LDefenseCount","k_player_prop_effect.LExpCount","k_player_prop_effect.LHpCount",
                                    "k_player_prop_effect.attackCount","k_player_prop_effect.defenseCount","k_player_prop_effect.expCount","k_player_prop_effect.hpCount",
                                    ]
            #--------------------------
            self.player_detail_ui_label.append(["攻击灵药".decode('utf-8'),"防御灵药".decode('utf-8'),"经验灵药".decode('utf-8'),"生命灵药".decode('utf-8')])
            self.player_detail_ui_label.append(["攻击圣药".decode('utf-8'),"防御圣药".decode('utf-8'),"经验圣药".decode('utf-8'),"生命圣药".decode('utf-8')])
            
                                    
        

        
        
    def run_bg_mysql_thread(self):
        #self.JobManager = []
        
        def __run(evt):
            dr.startWorker(self.refresh_gui, self.refresh_mysql)#, wargs=(), jobID = self.JobID)
        
        self.bg_thread_timer = wx.Timer(self)
        self.thread_abortEvent = dr.AbortEvent()
        self.thread_abortEvent.clear()
        self.Bind(wx.EVT_TIMER,__run,self.bg_thread_timer)
        
        self.bg_thread_timer.Start(5000)
        
    def OnProjSelect(self,e):
        self.refresh_mysql_flag = False
        
        
        
        
        for n in range(len(self.proj_items)):
            if self.proj_items["radio_%s" % n].GetValue():
                self.proj = self.proj_items["radio_%s" % n].GetLabel()
            
            
        self.db = self.xml_request.read_cfg()[self.proj]["database"]
        show_data = []
        
        for n in range(len(show_data),99):
            show_data.append(("","","",""))
        for nrow in range(len(show_data)):
            for ncol in range(len(show_data[nrow])):
                self.item_g.SetValue(nrow,ncol,str(show_data[nrow][ncol]).decode('utf-8'))
                self.skill_g.SetValue(nrow,ncol,str(show_data[nrow][ncol]).decode('utf-8'))
                self.equip_g.SetValue(nrow,ncol,str(show_data[nrow][ncol]).decode('utf-8'))
                self.weapon_g.SetValue(nrow,ncol,str(show_data[nrow][ncol]).decode('utf-8')) 
                
        if len(self.db) > 1:
            dn = ",".join(self.db)
        elif len(self.db) == 1:
            dn = self.db[0]
        else:
            dn = ""
        self.ch_db_v.SetLabel(str(dn))
        self.refresh_proj(self.proj)
        self.player = {}
        self.reset_player_detail_ui()
        
      
        
        
    def OnSearch(self,e):
        #for name ,value in self.sizer5_items.items():
            #if "line_box_info_vlaue_" in name:
                #value.SetEditable(False)
                #value.SetBackgroundColour("#F2F2F2")
        #for name ,value in self.sizer6_items.items():
            #if "line_box_info_vlaue_" in name:
                #value.SetEditable(False)
                #value.SetBackgroundColour("#F2F2F2")
        
        self.reset_player_detail_ui()
        self.errflag = False
        self.refresh_mysql_flag = True
        
        if self.bg_thread_timer.IsRunning():
            self.thread_abortEvent.set()
            self.bg_thread_timer.Stop()
            time.sleep(0.1)
            dr.startWorker(self.refresh_gui, self.refresh_mysql)
        self.bg_thread_timer.Start(10000)
        
    def refresh_mysql(self):
        if self.refresh_mysql_flag:
            self.Log.log("refreshing mysql" )
            st = time.time()
            self.queryname = self.filter.GetValue().strip()
            self.player = {}
            if self.queryname == "":
                self.Log.log("No player name or uc id inputed. query operation is not executed.")
            else:
                for db in self.db:
                    qd = self.mysql_request.refresh(self.proj,db,self.queryname)
                    if qd != None:
                        self.player[db] = qd
                self.Log.log("refresh mysql's action costs time [%s]s" % (time.time()-st))

    def refresh_xml(self):
        
        self.props_cfg = self.xml_request.getxml(self.prop_file)    
        self.skills_cfg = self.xml_request.getxml(self.skill_file)
        self.equips_cfg = self.xml_request.getxml(self.equip_file)
        print self.equips_cfg
        
    def refresh_gui(self,dr = None):
        
        if self.refresh_mysql_flag:
            st = time.time()
            self.Log.log("refreshing client's xml data." )
            self.Log.log("refresh xml's action costs time [%s]s" % (time.time()-st))
            self.refresh_xml()
            
            self.Log.log("refreshing gui." )
            st = time.time()
            self.showall()
            self.Log.log("refresh gui's action costs time [%s]s" % (time.time()-st))
        

            


    def menu_prepare(self):
        # Prepare the menu bar
        menuBar = wx.MenuBar()

        # 1st menu from left
        menu1 = wx.Menu()
        menu1.Append(101, "&配置Mysql连接参数".decode('utf-8'), "配置mysql的链接参数".decode('utf-8'))
        menu1.Append(102, "&关闭".decode('utf-8'), "关闭工具".decode('utf-8'))
        # Add menu to the menu bar
        menuBar.Append(menu1, "&配置".decode('utf-8'))

        # 2nd menu from left
        menu2 = wx.Menu()
        menu2.Append(201, "关于".decode('utf-8'))
        menuBar.Append(menu2, "&关于".decode('utf-8'))

        self.SetMenuBar(menuBar)


    def main_sizer_prepare(self):
        self.panel = wx.Panel(self,-1,size = (2000,2000))
        
        #----------------------------------
        sizer = wx.BoxSizer(wx.VERTICAL)
        sizer0 = wx.BoxSizer(wx.HORIZONTAL)
        sizer1 = wx.BoxSizer(wx.HORIZONTAL)
        sizer2 = wx.BoxSizer(wx.VERTICAL)
        sizer3 = wx.BoxSizer(wx.HORIZONTAL)
        
        self.player_detail_sizer = wx.BoxSizer(wx.VERTICAL)
        
        sizer5 = wx.BoxSizer(wx.VERTICAL)
        sizer6 = wx.BoxSizer(wx.VERTICAL)
        sizer7 = wx.BoxSizer(wx.VERTICAL)
        sizer8 = wx.BoxSizer(wx.VERTICAL)
        sizer9 = wx.BoxSizer(wx.VERTICAL)
        sizer10 = wx.BoxSizer(wx.VERTICAL)
        sizer11 = wx.BoxSizer(wx.HORIZONTAL)
        #----------------------------------
        proj_t = wx.StaticText(self.panel,-1,"当前使用项目:".decode('utf-8'))
        xml_cfg = self.xml_request.read_cfg()
        self.projs = list(set(xml_cfg.keys()))
        self.proj_id = self.prefer_cfg[1]
        self.proj = self.projs[self.proj_id]
        
        def inner_rad(p,projs):
            names = locals()
            for nproj in range(len(projs)):
                name = "radio_%s" % nproj
                if nproj == 0:
                    names[name] = wx.RadioButton( p, -1, projs[nproj], style = wx.RB_GROUP )
                else:
                    names[name] = wx.RadioButton( p, -1, projs[nproj])
                if str(self.proj_id) in name:
                    names[name].SetValue(True)
                else:
                    names[name].SetValue(False)
                    
            rd = {}
            for k,v in names.items():
                if "radio" in k:
                    rd[k] = v
            return rd
        
        sizer0.Add(proj_t,0,wx.CENTER|wx.ALL,5)
        self.proj_items = inner_rad(self.panel,self.projs)
        for n in range(len(self.proj_items)):
            sizer0.Add(self.proj_items["radio_%s" % n],0,wx.EXPAND,5)
            self.Bind(wx.EVT_RADIOBUTTON, self.OnProjSelect, self.proj_items["radio_%s" % n])
        
        #----------------------------------
        ch_db_t = wx.StaticText(self.panel,-1,"当前连接的Database是： ".decode('utf-8'))
        self.ch_db_v = wx.StaticText(self.panel,-1,"fightgame".decode('utf-8'))
        
        self.db = self.xml_request.read_cfg()[self.proj]["database"]
        if len(self.db) > 1:
            dn = ",".join(self.db)
        elif len(self.db) == 1:
            dn = self.db[0]
        else:
            dn = ""
        self.ch_db_v.SetLabel(str(dn))
        
        #self.ch_db_c = wx.Choice(self.panel,-1,choices=[])
        #self.ch_db_c.Bind(wx.EVT_CHOICE,self.OnSelect)    
        
        sizer0.Add(ch_db_t,0,wx.CENTER|wx.ALL,5)
        sizer0.Add(self.ch_db_v,0,wx.LEFT|wx.ALL,5)
        #----------------------------------
        sizer1.Add(wx.StaticLine(self.panel,-1,size=(1000,1)),0,wx.EXPAND,5)
        #----------------------------------
        
        self.filter_t = wx.StaticText(self.panel,-1,"查询您的UCID或者角色昵称：".decode('utf-8'))
        self.filter = wx.SearchCtrl(self.panel,-1, size=(500,25),style=wx.TE_PROCESS_ENTER)
        self.filter.ShowCancelButton(True)
        #----------------------------------
        
        sizer3.Add(self.filter_t,0,wx.LEFT|wx.BOTTOM|wx.ALL,5)
        sizer3.Add(self.filter,0,wx.CENTER|wx.ALL,5)
        self.db = self.xml_request.read_cfg()[self.proj]["database"]
        
        if len(self.db) > 1:
            dn = ",".join(self.db)
        elif len(self.db) == 1:
            dn = self.db[0]
        else:
            dn = ""
        self.ch_db_v.SetLabel(str(dn))
        
        
        sizer2.Add(sizer3,0,wx.EXPAND,5)
        sizer2.Add(wx.StaticLine(self.panel,-1,size=(1000,1)),0,wx.EXPAND,5)
        
        self.create_proj_sizer()
        
        
        
        
        
        sizer.Add(sizer0,0,wx.EXPAND,5)
        sizer.Add(sizer1,0,wx.EXPAND,5)
        sizer.Add(sizer2,0,wx.EXPAND,5)
        sizer.Add(self.player_detail_sizer,0,wx.EXPAND,5)
        sizer.Add(self.grid_sizer,0,wx.EXPAND,5)
        
        self.SetSizer(sizer)
        sizer.Fit(self)
        
        
    def reset_player_detail_ui(self):
        #self.player_detail_ui
        player_detail_ui_tags = [t for t in self.player_detail_ui.keys() if  "line_box_info_name_" in t]
        player_detail_ui_values = [t for t in self.player_detail_ui.keys() if  "line_box_info_vlaue_" in t]
        player_detail_ui_tags.sort()
        player_detail_ui_values.sort()
        
        for ntag in range(len(player_detail_ui_tags)):
            nums = re.findall(r"\d+",player_detail_ui_tags[ntag])
            if len(nums) != 2:
                print "met an fatal error of tag configuration"
                continue
            row = int(nums[0])
            col = int(nums[1])
            newLabel = self.player_detail_ui_label[row][col]
            self.player_detail_ui[player_detail_ui_tags[ntag]].SetLabel(newLabel)
            self.player_detail_ui[player_detail_ui_values[ntag]].SetValue("")

    def Evt_OnEditRoleSizer(self,e):  
        self.refresh_mysql_flag = False
        if self.player == {}:
            return
        try:
            playerdata = self.player[self.db[0]][self.proj]
        except:
            return
        
        if playerdata != {}:
            if self.filter.GetValue().strip() == "":
                wx.MessageBox("未填写帐号信息，不能编辑数据".decode('utf-8'),"Error",wx.OK)
                return
            
            for name ,value in self.player_detail_ui.items():
                if "line_box_info_vlaue_" in name:
                    value.SetEditable(True)
                    value.SetBackgroundColour("#E0EEEE")
       
    def Evt_OnSaveRoleSizer(self,e):
        self.refresh_mysql_flag = True
        try:
            playerdata = self.player[self.db[0]][self.proj]
        except:
            return
        if playerdata != {} and playerdata[self.tb_player] != {}:
            if self.filter.GetValue().strip() == "":
                wx.MessageBox("未填写帐号信息，不能提交数据".decode('utf-8'),"Error",wx.OK)
                return
        else:
            return
        
        for name ,value in self.player_detail_ui.items():
            if "line_box_info_vlaue_" in name:
                value.SetEditable(False)
                value.SetBackgroundColour("#F2F2F2")
                
        role_tags = [t for t in self.player_detail_ui.keys() if  "line_box_info_vlaue_" in t]
        role_tags.sort()
        role_tbtags = [x for x in self.player_detail_ui_value_tag if "self." not in x]
        role_data = {}
        
        for ntag in range(len(role_tags)):
            d = self.player_detail_ui[role_tags[ntag]].GetValue()
            if "-->" in d:
                role_data[role_tbtags[ntag]] = d[0]
            else:
                role_data[role_tbtags[ntag]] = d
        sql_update_player = []
        for k,v in role_data.items():
            m = [x.split('.') for x in k.split(',') if x.strip() != []]
            v = [x for x in v.split('/')]
            n = 0
            for tb,key in m:
                print v[n]
                sql_update_player.append("update %s.%s set %s='%s' where %s='%s';" % (self.db[0],tb,key,v[n],'id',playerdata[tb]["row_1"]["id"]))
                n += 1
        
        
        #for n in  sql_update_player:print n
        try:
            
            self.mysql_request.dosql(sql_update_player)
            wx.MessageBox("修改成功".decode("utf-8"),"Notice",wx.OK)
        except MySQLdb.Error,e:
            self.Log.log(e[1])
            return
        
         
         
    def refresh_data_player_detail_ui(self):   
    
        player_detail_ui_values = [t for t in self.player_detail_ui.keys() if  "line_box_info_vlaue_" in t]
        player_detail_ui_values.sort()
        
        
        player_detail_ui_tags = [t for t in self.player_detail_ui.keys() if  "line_box_info_name_" in t]
        player_detail_ui_tags.sort()
        
        player_detail_ui_value_tag = [t for t in self.player_detail_ui_value_tag if "self." not in t]
        
        try:
            self.playerdata = self.player[self.db[0]][self.proj]#[[x for x in  self.xml_cfg[self.proj].keys() if x[2:] == "player"][0]]
            self.tb_player = [x for x in  self.xml_cfg[self.proj].keys() if x[2:] == "player"][0]
            self.tb_player_prop = [x for x in  self.xml_cfg[self.proj].keys() if x[2:] == "player_prop"][0]
            self.tb_player_skill = [x for x in  self.xml_cfg[self.proj].keys() if x[2:] == "player_skill"][0]
            self.tb_player_equip = [x for x in  self.xml_cfg[self.proj].keys() if x[2:] == "player_equipment"][0]
            self.player_id = self.playerdata[self.tb_player]["row_1"]["id"]
        except:
            return

        for ntag in range(len(player_detail_ui_values)):
            nums = re.findall(r"\d+",player_detail_ui_values[ntag])
            if len(nums) != 2:# check if there's 2 number in names, cause it contains row number and col number 
                print "met an fatal error of tag configuration"
                continue
            
            tags = [x for x in player_detail_ui_value_tag[ntag].split(',') if x.strip() != ""]
            
            if tags == []:
                continue
            
            NewData = []
            for nitem in tags:
                s = nitem.split('.')
                tb = s[0]
                tag = s[1]                    
                argu_key = None
                if self.playerdata[tb] != {}:
                    if len(s) > 2:
                        argu_key = s[2]
                        argu_v = s[3]
                    if argu_key == None:
                        ag = str(self.playerdata[tb]["row_1"][tag]).decode("utf-8")
                        if tag == "role":
                            if ag == "2":
                                ag = "2 --> 法师".decode("utf-8")
                            elif ag == "1":
                                ag = "1 --> 战士".decode("utf-8")
                            #elif ag == "2":
                                #ag = "箭灵_2".decode("utf-8")
                        NewData.append(ag)
                    else:
                        d = self.playerdata[tb]
                        
                        ag = [x[tag] for x in d.values() if str(x[argu_key]) == (argu_v)]
                        
                        NewData.append(str(ag).decode("utf-8"))
                        
            NewData = '/'.join(NewData)
            OldData = self.player_detail_ui[player_detail_ui_values[ntag]].GetValue()

            self.player_detail_ui[player_detail_ui_values[ntag]].SetValue(NewData)
            if OldData != "" and OldData != NewData:
                self.player_detail_ui[player_detail_ui_values[ntag]].SetStyle(0, 47, wx.TextAttr("RED", wx.NullColour))
            else:
                self.player_detail_ui[player_detail_ui_values[ntag]].SetStyle(0, 47, wx.TextAttr("#228B22",wx.NullColour))
                
    def refresh_data_player_prop_ui(self):
        
        show_data = []
        try:
            props_data = self.player[self.db[0]][self.proj][self.tb_player_prop]
        except:
            props_data = {}
            
        if props_data != {}:
            
            k = props_data.keys()
            k.sort()
            for n in k:
                m = props_data[n]
                k1 = m.keys()
                show_data.append((m[[x for x in k1 if "id" == x.lower()][0]],\
                                  self.props_cfg[m[[x for x in k1 if "prop" in x.lower() and "id" in x.lower()][0]]].attrib["name"],\
                                  m[[x for x in k1 if "prop" in x.lower() and "id" in x.lower()][0]],\
                                  m[[x for x in k1 if "count" == x.lower()][0]]))
        
        show_data.sort(lambda x,y:cmp(int(x[2]),int(y[2])))
        
        for n in range(len(show_data),50):
            show_data.append(("","","",""))
        for nrow in range(len(show_data)):
            for ncol in range(len(show_data[nrow])):
                self.item_g.SetValue(nrow,ncol,str(show_data[nrow][ncol]).decode('utf-8'))

    def refresh_data_player_skill_ui(self):
        show_data = []
        try:
            skills_data = self.player[self.db[0]][self.proj][self.tb_player_skill]
        except:
            skills_data = {}
        
        if skills_data != {}:
            k = skills_data.keys()
            k.sort()
            for n in k:
                m = skills_data[n]
                k1 = m.keys()
                
                show_data.append((m[[x for x in k1 if "id" == x.lower()][0]],\
                                  self.skills_cfg[m[[x for x in k1 if "skill" in x.lower() and "id" in x.lower()][0]]].attrib["name"],\
                                  m[[x for x in k1 if "skill" in x.lower() and "id" in x.lower()][0]],\
                                  m[[x for x in k1 if "level" == x.lower()][0]]))
        
        show_data.sort(lambda x,y:cmp(int(x[2]),int(y[2])))
        for n in show_data:print n
        for n in range(len(show_data),99):
            show_data.append(("","","",""))
        for nrow in range(len(show_data)):
            for ncol in range(len(show_data[nrow])):
                self.skill_g.SetValue(nrow,ncol,str(show_data[nrow][ncol]).decode('utf-8'))
                
    
    def refresh_data_player_equip_ui(self):
        equip_colors = {
                        1:"白色",
                        2:"蓝色",
                        3:"紫色",
                        4:"橙色",
        }
        
        show_data = []
        try:
            equips_data = self.player[self.db[0]][self.proj][self.tb_player_equip]
        except:
            equips_data = {}
        
        if equips_data != {}:
            k = equips_data.keys()
            k.sort()
            for n in k:
                m = equips_data[n]
                k1 = m.keys()
                equip_xml = self.equips_cfg[m[[x for x in k1 if "equip" in x.lower() and "id" in x.lower()][0]]]
                equip_color =  equip_xml.attrib["color"]
                
                equipname = equip_xml.attrib["name"] +" - " + equip_colors[int(equip_color)] 
                
                show_data.append((m[[x for x in k1 if "id" == x.lower()][0]],\
                                  equipname,\
                                  m[[x for x in k1 if "equip" in x.lower() and "id" in x.lower()][0]],\
                                  m[[x for x in k1 if "extras" == x.lower()][0]]))
        
        show_data.sort(lambda x,y:cmp(int(x[2]),int(y[2])))
        for n in range(len(show_data),99):
            show_data.append(("","","",""))
        for nrow in range(len(show_data)):
            for ncol in range(len(show_data[nrow])):
                self.equip_g.SetValue(nrow,ncol,str(show_data[nrow][ncol]).decode('utf-8'))

    def create_proj_sizer(self):
        #=======================================================================
        # role_detail
        #=======================================================================
        self.player_detail_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label="角色基础数据".decode('utf-8')), wx.VERTICAL)
        self.player_detail_ui = self.__make_ui_code(self.player_detail_ui_label,self.player_detail_sizer)

        #player_detail_ui_values = [t for t in self.player_detail_ui.keys() if  "line_box_info_vlaue_" in t]
        #player_detail_ui_values.sort()
        
        button_tags = [t for t in self.player_detail_ui.keys() if  "line_box_info_button_" in t]
        button_tags.sort()
        tags = [x.split('.')[1] for x in self.player_detail_ui_value_tag if x.strip() != "" and "self." in x.strip()]
        
        for k in range(len(button_tags)):
            self.Bind(wx.EVT_BUTTON, getattr(self,"%s" % tags[k]), self.player_detail_ui[button_tags[k]])

        #=======================================================================
        # grid
        #=======================================================================
        self.grid_sizer = wx.BoxSizer(wx.HORIZONTAL)
        #-------------------------------------------------
        propgrid_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label="角色道具数据".decode('utf-8')), wx.VERTICAL)
        self.item_g = self.__make_grid_code(['MysqlID'.decode('utf-8'), '道具名'.decode('utf-8'),'道具ID'.decode('utf-8'), '道具数量'.decode('utf-8')])
        self.item_g.SetMinSize((320,300))
        #-------------------------------------------------
        self.weapongrid_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label="角色武器数据".decode('utf-8')), wx.VERTICAL)
        self.weapon_g = self.__make_grid_code(['MysqlID'.decode('utf-8'), '武器名'.decode('utf-8'),'武器ID'.decode('utf-8'), '武器等级'.decode('utf-8')])
        self.weapon_g.SetMinSize((320,300))
        #-------------------------------------------------
        skillgrid_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label="角色技能数据".decode('utf-8')), wx.VERTICAL)
        self.skill_g = self.__make_grid_code(['MysqlID'.decode('utf-8'), '技能名'.decode('utf-8'),'技能ID'.decode('utf-8'), '技能等级'.decode('utf-8')])
        self.skill_g.SetMinSize((320,300))
        
        #-------------------------------------------------
        equipment_sizer = wx.StaticBoxSizer(wx.StaticBox(self.panel, -1, label="角色装备数据".decode('utf-8')), wx.VERTICAL)
        self.equip_g = self.__make_grid_code(['MysqlID'.decode('utf-8'), '装备名'.decode('utf-8'),'装备ID'.decode('utf-8'), '等级/属性'.decode('utf-8')])
        self.equip_g.SetMinSize((320,300))
        
        #-------------------------------------------------
        item_ot = wx.Button(self.panel,-1,"设置道具数量".decode('utf-8'))
        weapon_ot = wx.Button(self.panel,-1,"设置武器等级".decode('utf-8'))
        skill_ot = wx.Button(self.panel,-1,"设置技能等级".decode('utf-8'))
        equip_ot = wx.Button(self.panel,-1,"设置装备等级".decode('utf-8'))
        #-------------------------------------------------
        self.Bind(wx.EVT_BUTTON,self.OnOt_Prop,item_ot)
        self.Bind(wx.EVT_BUTTON,self.OnOt_Weapon,weapon_ot)            
        self.Bind(wx.EVT_BUTTON,self.OnOt_Skill,skill_ot)
        self.Bind(wx.EVT_BUTTON,self.OnOt_Equip,equip_ot)
        #-------------------------------------------------
        all_weapon = wx.Button(self.panel,-1,"一键全武器设置等级".decode('utf-8'))
        self.all_weapon_lvl = wx.TextCtrl(self.panel,-1,"1",size=((50,20)))                
        all_skill = wx.Button(self.panel,-1,"一键全技能设置等级".decode('utf-8'))
        self.all_skill_lvl = wx.TextCtrl(self.panel,-1,"1",size=((50,20)))
        all_equip = wx.Button(self.panel,-1,"一键拥有高级套装".decode('utf-8'))
        
        self.all_equip_colorstr = wx.StaticText(self.panel,-1,"颜色")
        self.all_equip_color = wx.TextCtrl(self.panel,-1,"1",size=((50,20)))
        self.all_equip_lvlstr = wx.StaticText(self.panel,-1,"等级")
        self.all_equip_lvl = wx.TextCtrl(self.panel,-1,"1",size=((50,20)))
        self.all_equip_partstr = wx.StaticText(self.panel,-1,"部位")
        self.all_equip_part = wx.TextCtrl(self.panel,-1,"0",size=((50,20)))
                               
        weaponall_sizer = wx.BoxSizer(wx.HORIZONTAL)
        skillall_sizer = wx.BoxSizer(wx.HORIZONTAL)
        equipall_sizer1 = wx.BoxSizer(wx.HORIZONTAL)
        equipall_sizer2 = wx.BoxSizer(wx.HORIZONTAL)

        
        
        skillall_sizer.Add(all_skill,0,wx.LEFT|wx.ALL,5)
        skillall_sizer.Add(self.all_skill_lvl,0,wx.LEFT|wx.ALL,5) 

        equipall_sizer1.Add(self.all_equip_colorstr,0,wx.LEFT|wx.ALL,5)
        equipall_sizer1.Add(self.all_equip_color,0,wx.LEFT|wx.ALL,5)        
        equipall_sizer1.Add(self.all_equip_lvlstr,0,wx.LEFT|wx.ALL,5)
        equipall_sizer1.Add(self.all_equip_lvl,0,wx.LEFT|wx.ALL,5)
        equipall_sizer1.Add(self.all_equip_partstr,0,wx.LEFT|wx.ALL,5)
        equipall_sizer1.Add(self.all_equip_part,0,wx.LEFT|wx.ALL,5)        
        
        equipall_sizer2.Add(all_equip,0,wx.LEFT|wx.ALL,5)
        weaponall_sizer.Add(all_weapon,0,wx.LEFT|wx.ALL,5)
        weaponall_sizer.Add(self.all_weapon_lvl,0,wx.LEFT|wx.ALL,5)
        
          
        propgrid_sizer.Add(self.item_g,0,wx.EXPAND,5)
        propgrid_sizer.Add(item_ot,0,wx.EXPAND,5)
        
        self.weapongrid_sizer.Add(self.weapon_g,0,wx.EXPAND,5)
        self.weapongrid_sizer.Add(weapon_ot,0,wx.EXPAND,5)
        self.weapongrid_sizer.Add(weaponall_sizer,0,wx.EXPAND,5)
        
        skillgrid_sizer.Add(self.skill_g,0,wx.EXPAND,5)
        skillgrid_sizer.Add(skill_ot,0,wx.EXPAND,5)
        skillgrid_sizer.Add(skillall_sizer,0,wx.EXPAND,5)
        
        
        equipment_sizer.Add(self.equip_g,0,wx.EXPAND,5)
        equipment_sizer.Add(equip_ot,0,wx.EXPAND,5)
        equipment_sizer.Add(equipall_sizer1,0,wx.EXPAND,5)
        equipment_sizer.Add(equipall_sizer2,0,wx.EXPAND,5)
        
                
        self.grid_sizer.Add(propgrid_sizer,0,wx.EXPAND,5)
        self.grid_sizer.Add(skillgrid_sizer,0,wx.EXPAND,5)
        self.grid_sizer.Add(equipment_sizer,0,wx.EXPAND,5)
        self.grid_sizer.Add(self.weapongrid_sizer,0,wx.EXPAND,5)
   
        self.Bind(wx.EVT_BUTTON,self.Evt_AllSkillOT,all_skill)
              
    def __evt_binding(self):
        
        #=======================================================================
        # 菜单栏的事件绑定
        #=======================================================================
        self.Bind(wx.EVT_MENU, self.Evt_MenuEvt101, id=101)
        self.Bind(wx.EVT_MENU, self.Evt_MenuEvt102, id=102)
        self.Bind(wx.EVT_MENU, self.Evt_MenuEvt201, id=201)

        #=======================================================================
        # 搜索按钮的事件绑定
        #=======================================================================
        self.filter.Bind(wx.EVT_SEARCHCTRL_CANCEL_BTN,lambda e: self.filter.SetValue(''))
        self.filter.Bind(wx.EVT_TEXT_ENTER, self.OnSearch)
        #=======================================================================
        # 界面编辑，保存按钮事件绑定，放在sizer处理中单独进行
        #=======================================================================

        #=======================================================================
        # 关闭界面的事件绑定
        #=======================================================================
        self.Bind(wx.EVT_CLOSE, self.Evt_OnCloseWindow)
        
        
    def Evt_MenuEvt101(self,e):
        def __compare(old_d,new_d):
            
            for n in old_d:
                if int(n[1]) == 1:
                    o_ip = n[2]
                    o_port = n[3]
                    o_user = n[4]
                    o_pass = n[5]
                    o_char = n[6]
                     
            for m in new_d:
                if int(m[1]) == 1:
                    n_ip = m[2]
                    n_port = m[3]
                    n_user = m[4]
                    n_pass = m[5]
                    n_char = m[6]
            
            if o_ip != n_ip:
                return False
            if o_port != n_port:
                return False
            if o_user != n_user:
                return False
            if o_pass != n_pass:
                return False
            if o_char != n_char:
                return False
            return True
        
        dlg = DBConfigDialog()
        dlg.ShowModal()
        #self.cfg_new = self.sqlite_request.get()[0]
        #if not __compare(self.db_cfg,self.cfg_new):
            #self.Evt_OnCloseWindow(e)
            #frame = GUITool(None, self.Title_Msg)
            #frame.Show()
            #frame.Center()
        
    def Evt_MenuEvt102(self,e):
        self.Evt_OnCloseWindow(e)
        
    def Evt_MenuEvt201(self,e):
        dlg = wx.MessageDialog(self, "Thank you for using this tool which designed for uc's game testing!\nif you meet any problems when you're using, please contact me with chengjie@ucweb.com",
                               'Ion Hammer albertcheng',
                               wx.OK | wx.ICON_INFORMATION
                               #wx.YES_NO | wx.NO_DEFAULT | wx.CANCEL | wx.ICON_INFORMATION
                               )
        dlg.ShowModal()
        dlg.Destroy()
          
    def Evt_OnCloseWindow(self, evt):
        try:
            radio_proj_inx = self.projs.index(self.proj)
        except:
            radio_proj_inx = 0
        self.sqlite_request.dosql(["update prefer set lastprojid='%s';" % (radio_proj_inx)])
        
        try:
            self.thread_abortEvent.set()
        except:
            self.Destroy()
        self.Destroy() 
         


    def showall(self):
        if self.player != []:
            self.refresh_data_player_detail_ui()
            self.refresh_data_player_prop_ui()
            self.refresh_data_player_skill_ui()
            self.refresh_data_player_equip_ui()
            
    def __get_name_by_id(self,l,idx,tag):
        for m in l:
            if str(m[0]) == str(idx):
                return m[tag]  
    

    def __show_weapon_data(self):
        weapons_data = []
        show_data = []
        try:
            weapons_data = self.player[self.db[0]][self.proj][[x for x in  self.xml_cfg[self.proj].keys() if x[2:] == "player_weapon"][0]]
        except:
            return
        if self.use_data["weapon"] != ():
            self.weapons_cfg = self.xml_request.getxml("weapons.xml","<weapon id=")

        
        for nitem in weapons_data:
            item_weapons_id = int(nitem[2])
            item_lvl = int(nitem[3])
            item_idx = int(nitem[0])
            item_name = self.__get_name_by_id(self.weapons_cfg,item_weapons_id,1)
            show_data.append((item_idx,item_name,item_lvl))
        
        show_data.sort(lambda x,y:cmp(x[2],y[2]))
        for nitem in range(len(show_data),99):
            show_data.append(("","","",""))
        for nrow in range(len(show_data)):
            for ncol in range(len(show_data[nrow])):
                self.weapon_g.SetValue(nrow,ncol,str(show_data[nrow][ncol]).decode('utf-8'))
                                  
    def OnBEVipSizer(self,e):
        if self.filter.GetValue().strip() == "":
            self.Update_Flag = False
            return
        viptime = int(time.time()*1000) + 10000000000
        #ssdz|misc2|update|update
        role_tags = [t for t in self.sizer6_items.keys() if  "line_box_info_vlaue_" in t]
        role_tags.sort()
        
        
        p_db = self.ch_db_c.GetStringSelection().strip()
        vip_data = {}
        for ntag in range(len(self.sizer6_Tag_Area)):
            vip_data[self.sizer6_Tag_Area[ntag]] = self.sizer6_items[role_tags[ntag]].GetValue()
        sql_update_misc = [  self.use_cfg_sql["misc2"][1] % (p_db,\
                                                       viptime,\
                                                        vip_data["last_login_time"],\
                                                        self.player_id)]    
        
        try:
            self.dbh.dosql(sql_update_misc)
        except MySQLdb.Error,e:
            self.Log.log(e[1])
            return
        self.Update_Flag = True 
        self.__show_vipdata()
    
    def Evt_AllWeaponOT(self,e):
        pass
        #self._set_all_value(self.all_weapon_lvl,"weapon", "<weapon id=","weapons.xml","delallweapon")
        
    def Evt_AllSkillOT(self,e):
                
        try:
            skills_data = self.player[self.db[0]][self.proj][self.tb_player_skill]
        except:
            skills_data = {}
        if skills_data != {}:
            self._set_all_value(self.all_skill_lvl, self.skill_file, skills_data, "skill", self.tb_player_skill)
        else:
            pass
            
        
        
    def _set_all_value(self,obj=None,fn = None, data = None, key = None, tb = None):
        
        if self.proj == "ssdz":
            range_txt = "0-15"
            range_v = 16
        elif self.proj == "douhun":
            range_txt = "0-5"
            range_v = 6
        all_lvl_txt = obj.GetValue()
        all_lvl = re.findall(r"\d+",all_lvl_txt)
        
        if all_lvl == []:
            wx.MessageBox("请输入%s的整型数值." % range_txt,"Error",wx.OK)
            return
        all_lvl = int(all_lvl[0])
        obj.SetValue(str(all_lvl))
        
        if all_lvl not in range(0,range_v):
            wx.MessageBox("请输入%s的整型数值." % range_txt,"Error",wx.OK)
            return
        
        
        idx  = self.filter.GetValue()
        if idx == "":
            wx.MessageBox("未输入查询的帐号.","Error", wx.OK)
            return
        
        have_ids =  [int(x["id"]) for x in data.values()]
        base_del = "delete from %s.%s where `%s`='%s';" 
        
        sqls = [base_del %(self.db[0], tb, "id", n) for n in have_ids]
        
        
        Set_ids = []
        if self.proj == "ssdz":
            if key == "skill":
                for v in self.skills_cfg.values():
                    if v.attrib["isLearn"] == "true":
                        Set_ids.append(int(v.attrib["id"]))
                        
        elif self.proj == "douhun":
            if key == "skill":
                for v in self.skills_cfg.values():
                    if str(v.attrib["group"]) != "0":
                        Set_ids.append(int(v.attrib["id"]))
        
            
        try:
            self.dosql(sqls)
            wx.MessageBox("Data Applied Successfully.", "SSSSSS", wx.OK)
        except MySQLdb.Error,e:
            self.Log.log(e[1])
            wx.MessageBox("Data Applied Failed.\n"+e[1], "FFFFFFFFF", wx.OK)
        return
    
    
    def OnOt_Equip(self,e):
        self.refresh_mysql_flag = False
        idx = self.filter.GetValue().strip()
        if idx == "":
            wx.MessageBox("请先在搜索框填写要监控的ID或昵称".decode('utf-8'),"ERROR",wx.OK)
            return
        if self.player == {}:
            self.Log.log("Player Data is empty.")
            return   
        if self.proj != "ssdz":
            wx.MessageBox("当前只支持松鼠大战对装备进行设置，若要改变天劫装备属性，请在上方的数据框中修改后，右键点击保存即可".decode("utf-8"),"ERROR",wx.OK)
            return
        wx.MessageBox("当前功能只支持vip，请充值后联系管理员开通此功能".decode("utf-8"),"ERROR",wx.OK)
        return   
         
    def OnOt_Prop(self,e):
        
        self.refresh_mysql_flag = False
        idx = self.filter.GetValue().strip()
        if idx == "":
            wx.MessageBox("请先在搜索框填写要监控的ID或昵称".decode('utf-8'),"ERROR",wx.OK)
            return
        if self.player == {}:
            self.Log.log("Player Data is empty.")
            return
        
        Tags = ["是否生成".decode('utf-8'),"道具名".decode('utf-8'),"道具ID".decode('utf-8'),"道具数量".decode('utf-8')]
        
        #self.player_id = self.
        chd = ':0,1,10,100,9999'
        
        pc = DataConfigDialog(self.proj,"道具生成配置界面".decode('utf-8'),\
                              self.prop_file,\
                              "prop",\
                              self.player[self.db[0]][self.proj],\
                              self.tb_player_prop,\
                              self.db[0],\
                              self.player_id,\
                              Tags,\
                              chd,
                              self.mysql_request)
        
        pc.ShowModal()
        pc.Destroy()
        self.refresh_mysql_flag = True

        
    def OnOt_Skill(self,e):
        self.refresh_mysql_flag = False
        idx = self.filter.GetValue().strip()
        if idx == "":
            wx.MessageBox("请先在搜索框填写要监控的ID或昵称".decode('utf-8'),"ERROR",wx.OK)
            return
        Tags = ["是否生成".decode('utf-8'),"技能名".decode('utf-8'),"技能ID".decode('utf-8'),"技能等级".decode('utf-8')]
        
        chd = ':0,1,5'
        
        pc = DataConfigDialog(self.proj,"技能生成配置界面".decode('utf-8'),self.skill_file,\
                              "skill",\
                              self.player[self.db[0]][self.proj],\
                              self.tb_player_skill,\
                              self.db[0],\
                              self.player_id,\
                              Tags,\
                              chd,
                              self.mysql_request)
        
        pc.ShowModal()
        pc.Destroy()
        self.refresh_mysql_flag = True


        
        
  
    def OnOt_Weapon(self,e):
        self.refresh_mysql_flag = False
        idx = self.filter.GetValue().strip()
        if idx == "":
            wx.MessageBox("请先在搜索框填写要监控的ID或昵称".decode('utf-8'),"ERROR",wx.OK)
            return
        Tags = ["是否生成".decode('utf-8'),"武器名".decode('utf-8'),"武器ID".decode('utf-8'),"武器等级".decode('utf-8')]
        
        
        #self.player_id = self.
        chd = ':0,1,10,100,9999'
        
        pc = DataConfigDialog(self.proj,"技能生成配置界面".decode('utf-8'),self.prop_file,\
                              "<prop id=",self.player[self.db[0]][self.proj],\
                              self.tb_player_prop,\
                              self.db[0],\
                              self.player_id,\
                              Tags,\
                              chd,
                              self.mysql_request)
        
        pc.ShowModal()
        pc.Destroy()
        self.refresh_mysql_flag = True
        
        self.refresh_mysql_flag = False
        idx = self.filter.GetValue().strip()
        if idx == "":
            wx.MessageBox("请先在搜索框填写要监控的ID或昵称".decode('utf-8'),"ERROR",wx.OK)
            return
        
        Tags = ["是否生成".decode('utf-8'),"武器名".decode('utf-8'),"武器等级".decode('utf-8')]
        
        
        chd = ':0,1,5,10,15'
        proj = "ssdz"
        
        pc = DataConfigDialog(proj,"武器生成配置界面".decode('utf-8'),"weapons.xml",\
                              "<weapon id=",self.use_data["weapon"],\
                              "weapon",\
                              self.ch_db_c.GetStringSelection().strip(),\
                              self.player_id,\
                              Tags,\
                              chd)
        pc.ShowModal()
        pc.Destroy()
         

    

    def __make_grid_code(self,Tags):
        colsize = [(0,60),
                   (1,100),
                   (2,50),
                   (3,60)]
        dt = [GRID_STRING,GRID_STRING,GRID_STRING,GRID_STRING]
        return CustTableGrid(self.panel,Tags,dt,colsize,[])      
                
    def __make_ui_code(self,data_label,make_sizer):
        l_names = locals()
        bl = []
        for nline in range(len(data_label)):
            line_box_name = "line_box_%s" % nline            
            l_names[line_box_name] = wx.BoxSizer(wx.HORIZONTAL)            
            for nitem in  range(len(data_label[nline])):
                line_box_info_name = "line_box_info_name_%s_%s" % (nline,nitem)
                line_box_name_value = "line_box_info_vlaue_%s_%s" % (nline,nitem)
                line_box_button = "line_box_info_button_%s_%s" % (nline,nitem)
                if "button|" in data_label[nline][nitem]:
                    l_names[line_box_button] = wx.Button(self.panel,-1,data_label[nline][nitem].split('|')[1])
                    bl.append(line_box_button)
                else:
                    l_names[line_box_info_name] = wx.StaticText(self.panel,-1, data_label[nline][nitem])
                    l_names[line_box_name_value] = wx.TextCtrl(self.panel,-1,"",style= wx.TE_READONLY|wx.TE_RICH2)#16 is readonly
                    l_names[line_box_info_name].SetMinSize((80,20))
                    l_names[line_box_name_value].SetMinSize((110,20))
                    l_names[line_box_name_value].SetBackgroundColour("#F2F2F2")
                    l_names[line_box_name].Add(l_names[line_box_info_name],0,wx.EXPAND|wx.RIGHT,5)
                    l_names[line_box_name].Add(l_names[line_box_name_value],0,wx.EXPAND|wx.RIGHT,5)
            make_sizer.Add(l_names[line_box_name],0,wx.EXPAND,5)
        bl_sizer = wx.BoxSizer(wx.HORIZONTAL) 
        for k in bl:bl_sizer.Add(l_names[k],0,wx.EXPAND|wx.RIGHT,5)
        make_sizer.Add(bl_sizer,0,wx.CENTER|wx.ALIGN_RIGHT,5)
        return l_names
           
    
   


    def __update_sqlitedata(self):
        cfg = self.request.getcfg()
        if len(cfg) > 1:
            self.dbcfg = cfg[0]
            self.prefer = cfg[1]
            self.proj_data = self.prefer[0]
            self.projs = self.proj_data.split(';')
            #print self.prefer
            self.proj_id = int(self.prefer[1])
            self.database_id = self.prefer[2]
            self.proj = self.projs[self.proj_id]
        else:
            wx.MessageBox("Config.DB file is broken or missing, Please repair it.","Fatal Error",wx.OK)
            self.Destroy()
            sys.exit(1)

